// 导入node.js的path模块
const path = require('path')
// 导入clean-webpack-plugin-->每次打包时清空dis文件夹
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
// 导入html-webpack-plugin-->将html文件单独打包
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 导入mini-css-extract-plugin-->打包时将css单独打包
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// 导入webpack
const Webpack = require('webpack')
// 导入optimize-css-assets-webpack-plugin-->压缩css，需要借助cssnano
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
// 导入terser-webpack-plugin-->减少js体积(其中删除js的console.log和注释)
const TerserWebpackPlugin = require('terser-webpack-plugin')
// 导入wepack-bundle-analyzer-->查看打包后的依赖分析
const BundleAnalyzerPplugin = require('webpack-bundle-analyzer')
  .BundleAnalyzerPlugin
// 导入add-asset-html-webpack-plugin-->打包后在html文件中自动注入
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')

// 实例化CleanWebpackPlugin对象
const cleanPlugin = new CleanWebpackPlugin()
// 实例化HtmlWebpackPlugin对象
const htmlPlugin = new HtmlWebpackPlugin({
  title: 'spa-client-webpack', // 打包后html中的title
  filename: 'index.html', // 打包后的html文件名
  template: './public/index.html', // 打包时的html源文件
  favicon: '', //  添加特定的favicon
  minify: {
    removeComments: true, // 移除HTML中的注释
    collapseWhitespace: true, // 删除空白符和换行符
    minifyCSS: true // 压缩内联css
  }
})
// 实例化MiniCssExtractPlugin
const miniCssExtractPlugin = new MiniCssExtractPlugin({
  filename: 'static/css/[name]-[hash:6].css'
})
// 实例化Webpack.HotModuleReplacementPlugin
const hotModuleReplacementPlugin = new Webpack.HotModuleReplacementPlugin()
// 实例化OptimizeCssAssetsWebpackPlugin
const optimizeCssPlugin = new OptimizeCssAssetsWebpackPlugin({
  cssProcessor: require('cssnano'),
  cssProcessorOptions: {
    discardComments: {
      removeAll: true
    }
  }
})
// 实例化TerserWebpackPlugin对象
const terserPlugin = new TerserWebpackPlugin({
  parallel: 4,
  extractComments: true,
  terserOptions: {
    compress: {
      warnings: false,
      drop_console: true,
      drop_debugger: true,
      pure_funcs: ['console.log'] //移除console
    }
  }
})
// 实例化BundleAnalyzerPplugin对象
const analyzerPlugin = new BundleAnalyzerPplugin()
// 实例化AddAssetHtmlWebpackPlugin
const addAssetPlugin = new AddAssetHtmlWebpackPlugin({
  filepath: path.resolve(__dirname, './dll/lodash.dll.js')
})

module.exports = {
  mode: 'development', // 打包环境
  // mode: 'production', // 打包环境
  entry: './src/main.js', // 打包入口文件
  output: {
    path: path.resolve(__dirname, './dist'), // 输出文件结构
    filename: 'static/js/[name]-[hash:6].js'
    // publicPath: '//cdnUrl.com' // 指定存放js文件的CDN地址
  },
  module: {
    rules: [
      // css
      {
        test: /\.css$/,
        use: [
          //   'style-loader',
          // 使用mini-css-extract-plugin中的loader后，就不再需要使用style-loader
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader'
          },
          'postcss-loader'
        ],
        // 缩小文件范围loader
        include: path.resolve(__dirname, './src')
      },
      // scss
      {
        test: /\.scss$/,
        use: [
          //   'style-loader',
          // 使用mini-css-extract-plugin中的loader后，就不再需要使用style-loader
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader'
          },
          'sass-loader',
          'postcss-loader'
        ],
        include: path.resolve(__dirname, './src')
      },
      // url-->dispose image
      {
        test: /\.(png|jpe?g|gif)$/,
        use: {
          loader: 'url-loader',
          options: {
            name: 'image-[hash:8].[ext]', // 打包输出的名称
            outputPath: '/static/images/', // 打包输出的路径
            limit: 1024 * 10 // 小于2048才转换成base64
          }
        },
        include: path.resolve(__dirname, './src')
      },
      // js?
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        },
        include: path.resolve(__dirname, './src')
      }
    ]
  },
  optimization: {
    minimizer: [
      // 只有打包环境为production时才能生效
      terserPlugin
    ],
    // 代码分割-->此种方法弊端比较多，优先利用ES6的import进行动态导入
    splitChunks: {
      chunks: 'all'
    },
    concatenateModules: true
  },
  plugins: [
    cleanPlugin,
    htmlPlugin,
    miniCssExtractPlugin,
    hotModuleReplacementPlugin,
    optimizeCssPlugin,
    analyzerPlugin,
    addAssetPlugin
  ],
  devServer: {
    contentBase: './dist',
    open: true,
    port: 8080,
    hot: true,// 热更新替换
    hotOnly: true,
    proxy: {
      '/api': {
        target: 'http://localhost: 8080'
      }
    }
  },
  devtool: 'cheap-module-eval-source-map',
  resolve: {
    // 优化resolve.modules配置-->用于配置webpack去哪些目录下寻找第三方模块，默认是[node_modules]
    modules: [path.resolve(__dirname, './node_modules')],
    // 优化reslove.alias配置-->通过别名来将导入路径映射成一个新的导入路径
    alias: {
      '@': path.join(__dirname, './src')
    },
    // 优化reslove.extensions配置-->用于在导入没带文件后缀时，webpack会自动带上后缀后，去尝试查找文件是否存在
    extensions: ['.js', '.json', '.jsx', '.scss', 'css']
  }
  // 使用externals优化cdn资源-->需要在html文件中引入对应包的cdn地址，这样全局中就有对应的包名，例如jQuery
  // externals: {
  //   jquery: 'jQuery', // jquery通过script引入之后，全局中即有了jQuery变量
  // }
}
